/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cz.muni.fi.pb138.accountingRecords.web;

import cz.muni.fi.pb138.accountingRecords.Invoice;
import cz.muni.fi.pb138.accountingRecords.Item;
import cz.muni.fi.pb138.accountingRecords.PaymentType;
import cz.muni.fi.pb138.accountingRecords.Subject;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;

/**
 *
 * @author tuhar
 */
public class InvoiceForm {

    private String id;
    private Long invoiceNumber;
    private Subject distributor;
    private Subject consumer;
    private List<Item> items = new ArrayList<Item>();
    private PaymentType paymentType;
    private String invoicingDate;
    private String dueDate;
    private String bankAccount;
    private String drawer;//name and surname of person who issued invoice
    private Long variableSymbol;

    public static InvoiceForm extractFromRequest(HttpServletRequest request) {
        InvoiceForm invoiceForm = new InvoiceForm();
        String nextParameter = request.getParameter("invNum");
        if (nextParameter.equals("")) {
            invoiceForm.setInvoiceNumber(null);
        } else {
            try{
                invoiceForm.setInvoiceNumber(Long.parseLong(nextParameter));
            }catch(NumberFormatException ex){
                invoiceForm.setInvoiceNumber(null);
            }
        }
        nextParameter = request.getParameter("paymentType");
        if (nextParameter.equals("cash")) {
            invoiceForm.setPaymentType(PaymentType.CASH);
        } else if (nextParameter.equals("transaction")) {
            invoiceForm.setPaymentType(PaymentType.TRANSACTION);
        } else if (nextParameter.equals("creditCard")) {
            invoiceForm.setPaymentType(PaymentType.CREDITCARD);
        }
        nextParameter = request.getParameter("invoicingDate");
        if (nextParameter.equals("")) {
            invoiceForm.setInvoicingDate(null);
        } else {
            invoiceForm.setInvoicingDate(nextParameter);
        }
        nextParameter = request.getParameter("dueDate");
        if (nextParameter.equals("")) {
            invoiceForm.setDueDate(null);
        } else {
            invoiceForm.setDueDate(nextParameter);
        }
        nextParameter = request.getParameter("bankAccount");
        if (nextParameter.equals("")) {
            invoiceForm.setBankAccount(null);
        } else {
            invoiceForm.setBankAccount(nextParameter);
        }
        nextParameter = request.getParameter("drawer");
        if (nextParameter.equals("")) {
            invoiceForm.setDrawer(null);
        } else {
            invoiceForm.setDrawer(nextParameter);
        }
        nextParameter = request.getParameter("variableSymbol");
        if (nextParameter.equals("")) {
            invoiceForm.setVariableSymbol(null);
        } else {
            try{
                invoiceForm.setVariableSymbol(Long.parseLong(nextParameter));
            }catch(NumberFormatException ex){
                invoiceForm.setVariableSymbol(null);
            }
        }

        /*
         * parse distributor
         */

        Subject dist = new Subject();
        nextParameter = request.getParameter("disName");
        if (nextParameter.equals("")) {
            dist.setSubjectName(null);
        } else {
            dist.setSubjectName(nextParameter);
        }
        nextParameter = request.getParameter("disCity");
        if (nextParameter.equals("")) {
            dist.setCity(null);
        } else {
            dist.setCity(nextParameter);
        }
        nextParameter = request.getParameter("disStreet");
        if (nextParameter.equals("")) {
            dist.setStreet(null);
        } else {
            dist.setStreet(nextParameter);
        }
        nextParameter = request.getParameter("disStreetNum");
        if (nextParameter.equals("")) {
            dist.setNumber(null);
        } else {
            try{
                dist.setNumber(Integer.parseInt(nextParameter));
            }catch(NumberFormatException ex){
                dist.setNumber(null);
            }
        }
        nextParameter = request.getParameter("disPostalCode");
        if (nextParameter.equals("")) {
            dist.setPostalCode(null);
        } else {
            try{
                dist.setPostalCode(Integer.parseInt(nextParameter));
            }catch(NumberFormatException ex){
                dist.setPostalCode(null);
            }
        }
        nextParameter = request.getParameter("disPhone");
        if (nextParameter.equals("")) {
            dist.setPhone(null);
        } else {
            dist.setPhone(nextParameter);
        }
        nextParameter = request.getParameter("disMail");
        if (nextParameter.equals("")) {
            dist.setMail(null);
        } else {
            dist.setMail(nextParameter);
        }
        nextParameter = request.getParameter("disICO");
        if (nextParameter.equals("")) {
            dist.setIdNumber(null);
        } else {
            try{
                dist.setIdNumber(Integer.parseInt(nextParameter));
            }catch(NumberFormatException ex){
                dist.setIdNumber(null);
            }
        }
        invoiceForm.setDistributor(dist);

        /*
         * parse consumer
         */
        Subject con = new Subject();
        nextParameter = request.getParameter("conName");
        if (nextParameter.equals("")) {
            con.setSubjectName(null);
        } else {
            con.setSubjectName(nextParameter);
        }
        nextParameter = request.getParameter("conCity");
        if (nextParameter.equals("")) {
            con.setCity(null);
        } else {
            con.setCity(nextParameter);
        }
        nextParameter = request.getParameter("conStreet");
        if (nextParameter.equals("")) {
            con.setStreet(null);
        } else {
            con.setStreet(nextParameter);
        }
        nextParameter = request.getParameter("conStreetNum");
        if (nextParameter.equals("")) {
            con.setNumber(null);
        } else {
            try{
                con.setNumber(Integer.parseInt(nextParameter));
            }catch(NumberFormatException ex){
                con.setNumber(null);
            }
        }
        nextParameter = request.getParameter("conPostalCode");
        if (nextParameter.equals("")) {
            con.setPostalCode(null);
        } else {
            try{
                con.setPostalCode(Integer.parseInt(nextParameter));
            }catch(NumberFormatException ex){
                con.setPostalCode(null);
            }
        }
        nextParameter = request.getParameter("conPhone");
        if (nextParameter.equals("")) {
            con.setPhone(null);
        } else {
            con.setPhone(nextParameter);
        }
        nextParameter = request.getParameter("conMail");
        if (nextParameter.equals("")) {
            con.setMail(null);
        } else {
            con.setMail(nextParameter);
        }
        nextParameter = request.getParameter("conICO");
        if (nextParameter.equals("")) {
            con.setIdNumber(null);
        } else {
            try{
                con.setIdNumber(Integer.parseInt(nextParameter));
            }catch(NumberFormatException ex){
                con.setIdNumber(null);
            }
        }
        invoiceForm.setConsumer(con);

        List<Item> it = new ArrayList<Item>();
        int i = 1;
        while (request.getParameter("itemName" + i) != null) {
            Item item = new Item();
            nextParameter = request.getParameter("itemName" + i);
            if (nextParameter.equals("")) {
                item.setNote(null);
            } else {
                item.setNote(nextParameter);
            }
            nextParameter = request.getParameter("itemPrice" + i);
            if (nextParameter.equals("")) {
                item.setPriceForUnit(new BigDecimal(0));
            } else {
                try{
                    item.setPriceForUnit(new BigDecimal(nextParameter));
                }catch(Exception ex){
                    item.setPriceForUnit(new BigDecimal(0));
                }
            }
            nextParameter = request.getParameter("itemAmount" + i);
            if (nextParameter.equals("")) {
                item.setCount(null);
            } else {
                try{
                    item.setCount(Integer.parseInt(nextParameter));
                }catch(NumberFormatException ex){
                    item.setCount(null);
                }
            }
            i++;
            it.add(item);
        }
        invoiceForm.setItems(it);
        return invoiceForm;
    }

    public Invoice validateAndToInvoice(StringBuilder errors) {
        Invoice invoice = new Invoice();
        if (getInvoiceNumber() == null) {
            errors.append("Číslo faktúry nie je vyplnené").append(". <br />");
            invoice.setInvoiceNumber(null);
        } else {
            if (getInvoiceNumber() < 0) {
                errors.append("Číslo faktúry je záporné").append(". <br />");
                invoice.setInvoiceNumber(null);
            } else {
                invoice.setInvoiceNumber(getInvoiceNumber());
            }
        }
        invoice.setPaymentType(getPaymentType());
        if (getInvoicingDate() == null) {
            errors.append("Dátum vystavenia faktúry nie je vyplnený").append(". <br />");
            invoice.setInvoicingDate(null);
        } else {
            try {
                SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");
                invoice.setInvoicingDate(formatter.parse(getInvoicingDate()));
            } catch (ParseException e) {
                errors.append("Dátum vystavenia faktúry je v zlom formáte (správne:dd/mm/yyyy)").append(". <br />");
                invoice.setInvoicingDate(null);
            }
        }
        if (getDueDate() == null) {
            errors.append("Dátum splatnosti nie je vyplnený").append(". <br />");
            invoice.setDueDate(null);
        } else {
            try {
                SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");
                invoice.setDueDate(formatter.parse(getDueDate()));
            } catch (ParseException e) {
                errors.append("Dátum splatnosti faktúry je v zlom formáte (správne:dd/mm/yyyy)").append(". <br />");
                invoice.setDueDate(null);
            }
        }
        if (getBankAccount() != null) {
            if (!getBankAccount().matches("[1-9][0-9]{8}/[0-9]{4}")) {
                errors.append("Účet je v zlom tvare");
                invoice.setBankAccount(null);
            } else {
                invoice.setBankAccount(getBankAccount());
            }
        }
        if (getDrawer() == null) {
            errors.append("Vystaviteľ faktúry nie je vyplnený").append(". <br />");
            invoice.setDrawer(null);
        } else {
            invoice.setDrawer(getDrawer());
        }
        if (getVariableSymbol() != null) {
            if (getVariableSymbol() < 0l || getVariableSymbol() > 9999999999l) {
                errors.append("Variabilný symbol musí mať 1-10 číslic").append(". <br />");
                invoice.setVariableSymbol(null);
            } else {
                invoice.setVariableSymbol(getVariableSymbol());
            }
        }

        if (getDistributor() != null) {
            if (validateSubject(getDistributor(), "dodávateľa", errors)) {
                invoice.setDistributor(getDistributor());
            } else {
                invoice.setDistributor(null);

            }
        }
        if (getConsumer() != null) {
            if (validateSubject(getConsumer(), "odberateľa", errors)) {
                invoice.setConsumer(getConsumer());
            } else {
                invoice.setConsumer(null);
            }
        }
        int i = 1;
        List<Item> validatedItems = new ArrayList<Item>();

        for (int n = 0; n < items.size(); n++) {
            Item item = items.get(n);
            boolean fail = false;
            if (item.getNote() == null) {
                errors.append("Meno položky ").append(i).append(" nie je vyplnené").append(". <br />");
                fail = true;
            }
            if (item.getPriceForUnit() == new BigDecimal(0)) {
                errors.append("Cena položky ").append(i).append(" nie je vyplnené").append(". <br />");
                fail = true;
            } else {
                if (item.getPriceForUnit().compareTo(new BigDecimal(0)) <= 0) {
                    errors.append("Cena položky ").append(i).append(" je záporná alebo nie je vyplnená").append(". <br />");
                    fail = true;
                }
            }
            if (item.getCount() == null) {
                errors.append("Počet položky ").append(i).append(" nie je vyplnený").append(". <br />");
                fail = true;
            } else {
                if (item.getCount() < 0) {
                    errors.append("Počet položky ").append(i).append(" je záporný").append(". <br />");
                    fail = true;
                }
            }
            if (!fail) {
                validatedItems.add(item);
            }
            i++;
        }
        invoice.setItems(validatedItems);
        if (errors.length() > 0) {
            return null;
        } else {
            return invoice;
        }

    }

    public boolean validateSubject(Subject subject, String field, StringBuilder errors) {
        if (subject.getSubjectName() == null) {
            errors.append("Meno ").append(field).append(" nie je vyplnené").append(". <br />");
            return false;
        }
        if (subject.getCity() == null) {
            errors.append("Mesto ").append(field).append(" nie je vyplnené").append(". <br />");
            return false;
        }
        if (subject.getNumber() == null) {
            errors.append("Číslo ulice ").append(field).append(" nie je vyplnené").append(". <br />");
        } else {
            if (subject.getNumber() < 0) {
                errors.append("Číslo ulice ").append(field).append(" je záporné").append(". <br />");
                return false;
            }
        }
        if (subject.getPostalCode() == null) {
            errors.append("PSČ ").append(field).append(" nie je vyplnené").append(". <br />");
            return false;
        } else {
            if (subject.getPostalCode() < 10000 || subject.getPostalCode() > 80000) {
                errors.append("PSČ ").append(field).append(" je neplatné").append(". <br />");
                return false;
            }
        }
        if (subject.getPhone() != null) {
            if (!subject.getPhone().matches("\\+[1-9][0-9]{11}")) {
                errors.append("Telefón ").append(field).append(" je v zlom tvare").append(". <br />");
                return false;
            }
        }
        if (subject.getMail() != null) {
            if (!subject.getMail().matches(".+@.+")) {
                errors.append("E-mail ").append(field).append(" je v zlom tvare").append(". <br />");
                return false;
            }
        }
        if (subject.getIdNumber() != null) {
            if (subject.getIdNumber() < 10000000 || subject.getIdNumber() > 99999999) {
                errors.append("IČO ").append(field).append(" je neplatné").append(". <br />");
                return false;
            }
        }
        return true;
    }

    /**
     * @return the id
     */
    public String getId() {
        return id;
    }

    /**
     * @param id the id to set
     */
    public void setId(String id) {
        this.id = id;
    }

    /**
     * @return the invoiceNumber
     */
    public Long getInvoiceNumber() {
        return invoiceNumber;
    }

    /**
     * @param invoiceNumber the invoiceNumber to set
     */
    public void setInvoiceNumber(Long invoiceNumber) {
        this.invoiceNumber = invoiceNumber;
    }

    /**
     * @return the distributor
     */
    public Subject getDistributor() {
        return distributor;
    }

    /**
     * @param distributor the distributor to set
     */
    public void setDistributor(Subject distributor) {
        this.distributor = distributor;
    }

    /**
     * @return the consumer
     */
    public Subject getConsumer() {
        return consumer;
    }

    /**
     * @param consumer the consumer to set
     */
    public void setConsumer(Subject consumer) {
        this.consumer = consumer;
    }

    /**
     * @return the items
     */
    public List<Item> getItems() {
        return items;
    }

    /**
     * @param items the items to set
     */
    public void setItems(List<Item> items) {
        this.items = items;
    }

    /**
     * @return the paymentType
     */
    public PaymentType getPaymentType() {
        return paymentType;
    }

    /**
     * @param paymentType the paymentType to set
     */
    public void setPaymentType(PaymentType paymentType) {
        this.paymentType = paymentType;
    }

    /**
     * @return the invoicingDate
     */
    public String getInvoicingDate() {
        return invoicingDate;
    }

    /**
     * @param invoicingDate the invoicingDate to set
     */
    public void setInvoicingDate(String invoicingDate) {
        this.invoicingDate = invoicingDate;
    }

    /**
     * @return the dueDate
     */
    public String getDueDate() {
        return dueDate;
    }

    /**
     * @param dueDate the dueDate to set
     */
    public void setDueDate(String dueDate) {
        this.dueDate = dueDate;
    }

    /**
     * @return the bankAccount
     */
    public String getBankAccount() {
        return bankAccount;
    }

    /**
     * @param bankAccount the bankAccount to set
     */
    public void setBankAccount(String bankAccount) {
        this.bankAccount = bankAccount;
    }

    /**
     * @return the drawer
     */
    public String getDrawer() {
        return drawer;
    }

    /**
     * @param drawer the drawer to set
     */
    public void setDrawer(String drawer) {
        this.drawer = drawer;
    }

    /**
     * @return the variableSymbol
     */
    public Long getVariableSymbol() {
        return variableSymbol;
    }

    /**
     * @param variableSymbol the variableSymbol to set
     */
    public void setVariableSymbol(Long variableSymbol) {
        this.variableSymbol = variableSymbol;
    }
}
